package cn.openea.perpartner.meily.web.service.logistics.businessModule;

import cn.hutool.core.date.DateUtil;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.utils.DateUtils;
import cn.openea.perpartner.common.core.utils.StringUtils;
import cn.openea.perpartner.meily.constant.CommonConstants;
import cn.openea.perpartner.meily.constant.enums.ExpressCompany;
import cn.openea.perpartner.meily.constant.enums.ExpressStatus;
import cn.openea.perpartner.meily.constant.enums.LogisticsModule;
import cn.openea.perpartner.meily.rabbit.domain.BusinessDto;
import cn.openea.perpartner.meily.rabbit.domain.GroupDto;
import cn.openea.perpartner.meily.rabbit.service.impl.PublisherService;
import cn.openea.perpartner.meily.web.entity.Goods;
import cn.openea.perpartner.meily.web.entity.GroupBuyingSub;
import cn.openea.perpartner.meily.web.entity.LogisticsInfo;
import cn.openea.perpartner.meily.web.entity.dto.GroupBuyingSubDTOFactory;
import cn.openea.perpartner.meily.web.service.IGoodsService;
import cn.openea.perpartner.meily.web.service.IGroupBuyingSubService;
import cn.openea.perpartner.meily.web.service.ILogisticsInfoService;
import cn.openea.perpartner.meily.web.service.logistics.LogisticsQuery;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;

/**
 * @author ysk
 * @version 1.0.1
 * @Description 团购物流查询
 * @createTime 2023年05月10日 15:04:00
 */
@Slf4j
@Service(value = LogisticsModuleService.GROUP_BUY_LOGISTICS_QUERY)
public class GroupBuyLogisticsModuleService extends LogisticsModelAbstractService {

    @Resource
    private IGroupBuyingSubService groupBuyingSubService;
    @Resource
    private LogisticsQuery logisticsQuery;
    @Resource
    private GroupBuyingSubDTOFactory groupBuyingSubDTOFactory;
    @Resource
    private ILogisticsInfoService logisticsInfoService;
    @Resource
    private IGoodsService goodsService;
    @Autowired
    PublisherService publisherService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public LogisticsInfo findByModuleId(String moduleId) {
        GroupBuyingSub groupBuyingSub = Optional.ofNullable(groupBuyingSubService.getById(moduleId))
                .orElseThrow(() -> new ServiceException("订单不存在"));
        LogisticsInfo logisticsInfo = logisticsQuery.findByModuleAndModuleId(LogisticsModule.GROUPBUY, moduleId);
        if (logisticsInfo == null && "已发货".equals(groupBuyingSub.getOrderStatus())) {
            GroupBuyingSubDTOFactory.DetailsDto detailsDto = groupBuyingSubDTOFactory
                    .toDetailsDto.apply(groupBuyingSub);
            // 物流信息还没追踪，去查实时物流接口
            synchLogistics(groupBuyingSub,
                    ExpressCompany.getByCode(detailsDto.getExpressCompanyCode()),
                    detailsDto.getCourierNumber(),
                    detailsDto.getConsigneePhoneNum(),
                    null
            );
            return logisticsQuery.findByModuleAndModuleId(LogisticsModule.GROUPBUY, moduleId);
        }
        return logisticsInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void logisticsChange(ExpressCompany expressCompany, String id, String courierNumber) {
        GroupBuyingSub groupBuyingSub = Optional.ofNullable(groupBuyingSubService.getById(id))
                .orElseThrow(() -> new ServiceException("订单不存在"));
        // 获取商品信息
        Goods goods = Optional.ofNullable(goodsService.getById(groupBuyingSub.getGoodsId()))
                .orElseThrow(() -> new ServiceException("商品不存在"));
        String oldOrderStatus = groupBuyingSub.getOrderStatus();
        if ("已完成".equals(oldOrderStatus) || "已退款".equals(oldOrderStatus) || "已评价".equals(oldOrderStatus)) {
            throw new ServiceException("订单已完成，无法更新物流");
        }
        String logisticsId = "";
        if("已付款".equals(groupBuyingSub.getOrderStatus())){

            System.out.println("发货.......");

            // 发货
            groupBuyingSub.setDeliveryTime(DateUtils.getNow());
            groupBuyingSub.setOrderStatus("已发货");

            try {
                // 过期时间（当前时间 + 10天）
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = DateUtils.addDays(sdf.parse(DateUtil.now()),10);
                groupBuyingSub.setExpirationTime(sdf.format(date));

                System.out.println("过期时间expirationTime=" + groupBuyingSub.getExpirationTime());

                /**
                 * 首次发货后的动作 接入MQ
                 * TODO 48小时提醒收货、到期自动收货、  ---》 MQ （传入对象 JSONObject） --》 统一消费者
                 */
                System.out.println("************* 调用对应的业务处理下单成功后的动作 MQ *****************");
                // 业务参数
                JSONObject object = new JSONObject();
                object.put("id", groupBuyingSub.getId());

                // 延时执行时间
                Long ttl = DateUtil.betweenMs(sdf.parse(DateUtil.now()), DateUtils.addDays(sdf.parse(groupBuyingSub.getExpirationTime()), -2)); // 自动收货前48小时
                System.out.println("自动收货前48小时,延时执行时间ttl=" + ttl);

                GroupDto dto = new GroupDto();
                dto.setDelayTime(ttl); // 自动收货前48小时
                dto.setType("0");// 类型。0：自动收货前48小时发送收货通知；
                dto.setParams(object);

                System.out.println("48小时提醒收货dto=" + dto);
                System.out.println("************* MQ 执行结束！*****************");
                // 48小时提醒收货
                publisherService.execute(dto);

                /** ------------------------------------------------------------------------------------- */
                ttl = DateUtil.betweenMs(sdf.parse(DateUtil.now()), sdf.parse(groupBuyingSub.getExpirationTime()));
                System.out.println("到期自动收货,延时执行时间ttl=" + ttl);
                dto.setDelayTime(ttl);
                dto.setType("1");// 类型。// 1：到期自动收货；
                System.out.println("自动收货参数dto=" + dto);
                System.out.println("******************************");
                // 自动收货
                publisherService.execute(dto);

            } catch (ParseException e){
                e.printStackTrace();
            }

        } else if ("已发货".equals(groupBuyingSub.getOrderStatus())) {
            System.out.println("改物流.......");
            // 改物流
            String oldCourierNumber = groupBuyingSub.getCourierNumber();
            // 如果物流公司与物流单号与之前的一致，则不需要更新
            if (oldCourierNumber.equals(courierNumber)) {
                throw new ServiceException("新的物流信息与旧的物流信息一致，无需更新！");
            }
            // 之前的物流已经在运输中了
            LogisticsInfo logisticsInfo = this.findByModuleId(id);
            if (logisticsInfo != null && ExpressStatus.isInTransport(logisticsInfo.getStatus())) {
                throw new ServiceException("订单已经在运输中了，不可更新物流");
            }
            if (logisticsInfo != null) {
                logisticsId = logisticsInfo.getId();
            }
        }

        // 设置订单物流信息
        groupBuyingSub.setCourierNumber(courierNumber);
        GroupBuyingSubDTOFactory.DetailsDto detailsDto = groupBuyingSubDTOFactory
                .toDetailsDto.apply(groupBuyingSub);
        // 同步物流
        expressCompany = synchLogistics(groupBuyingSub,
                expressCompany,
                courierNumber,
                detailsDto.getConsigneePhoneNum(),
                logisticsId
        );
        // 设置快递信息
        groupBuyingSub.setExpressCompanyCode(expressCompany.getCode());
        groupBuyingSub.setCourierName(expressCompany.getName());

        // 修改订单信息
        groupBuyingSubService.updateById(groupBuyingSub);
        // 发送通知
        groupBuyingSubService.logisticsChangeNotify(groupBuyingSub, goods, !"已发货".equals(oldOrderStatus) ?
                CommonConstants.LOGISTICS.DELIVERY_ACTION : CommonConstants.LOGISTICS.CHANGE_LOGISTICS_ACTION);
    }

    @Override
    public LogisticsInfo findRealTimeLogistics(String moduleId) {
        GroupBuyingSub groupBuyingSub = Optional.ofNullable(groupBuyingSubService.getById(moduleId))
                .orElseThrow(() -> new ServiceException("订单不存在"));
        LogisticsInfo logisticsInfo = checkEventuallyLogistics(LogisticsModule.GROUPBUY, moduleId);
        if (logisticsInfo != null && logisticsInfo.isSing()) {
            // 这是最终的物流信息了，不可能还有更新
            return logisticsInfo;
        }
        GroupBuyingSubDTOFactory.DetailsDto detailsDto = groupBuyingSubDTOFactory
                .toDetailsDto.apply(groupBuyingSub);
        // 同步物流到自己表里面
        synchLogistics(groupBuyingSub,
                ExpressCompany.getByCode(detailsDto.getExpressCompanyCode()),
                detailsDto.getCourierNumber(),
                detailsDto.getConsigneePhoneNum(),
                logisticsInfo != null ? logisticsInfo.getId() : null
        );
        return logisticsQuery.findByModuleAndModuleId(LogisticsModule.GROUPBUY, moduleId);
    }

    @Override
    public void businessStatusSync(LogisticsInfo logisticsInfo) {
        if (StringUtils.isBlank(logisticsInfo.getId()) || StringUtils.isBlank(logisticsInfo.getModuleId())) {
            throw new ServiceException("物流Id和业务模块Id不能为空");
        }
        GroupBuyingSub groupBuyingSub = Optional.ofNullable(groupBuyingSubService.getById(logisticsInfo.getModuleId()))
                .orElseThrow(() -> new ServiceException("订单不存在"));
        if (groupBuyingSub.businessCompletion()) {
            // 业务完成
            logisticsInfoService.updateBusinessStatus(logisticsInfo.getId(), CommonConstants.LOGISTICS.BUSINESS_FINISH);
        }
    }
}
